package com.lagou.ipersistence.reflection.factory;

import com.lagou.ipersistence.reflection.ReflectionException;

import java.lang.reflect.Constructor;
import java.util.*;

/**
 * @author Yan Jiahong
 * Created on 2020/11/22
 */
public class DefaultObjectFactory implements ObjectFactory {
    @Override
    public <T> boolean isCollection(Class<?> type) {
        return Collection.class.isAssignableFrom(type);
    }
    
    @Override
    public <T> T create(Class<T> type) {
        return create(type, null, null);
    }
    
    public <T> T create(Class<T> type, List<Class<?>> constructorTypes, List<Object> constructorArgs) {
        Class<?> classToCreate = resolveInterface(type);
        return (T) instantiateClass(classToCreate, constructorTypes, constructorArgs);
    }
    
    public <T> T instantiateClass(Class<T> type, List<Class<?>> constructorTypes, List<Object> constructorArgs) {
        try {
            Constructor<T> constructor;
            if (constructorTypes == null || constructorArgs == null) {
                constructor = type.getDeclaredConstructor();
                if (!constructor.isAccessible()) {
                    constructor.setAccessible(true);
                }
                return constructor.newInstance();
            }
        } catch (Exception e) {
            throw new ReflectionException("实例化 " + type + "失败!", e);
        }
        return null;
    }
    
    protected Class<?> resolveInterface(Class<?> type) {
        Class<?> classToCreate;
        if (type == List.class || type == Collection.class || type == Iterable.class) {
            classToCreate = ArrayList.class;
        } else if (type == Map.class) {
            classToCreate = HashMap.class;
        } else if (type == SortedSet.class) {
            classToCreate = TreeSet.class;
        } else if (type == Set.class) {
            classToCreate = HashSet.class;
        } else {
            classToCreate = type;
        }
        return classToCreate;
    }
}
